package cn.git.shiro.config;

import cn.git.shiro.realm.CustomRealm;
import net.sf.ehcache.CacheManager;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.io.ResourceUtils;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

/**
 * @description: shiro配置文件类
 * @program: bank-credit-sy
 * @author: lixuchun
 * @create: 2024-03-26
 */
@Configuration
public class ShiroConfig {

   @Autowired
   private CustomRealm customRealm;

   /**
    * 创建自定义的realm
    * @return
    */
   @Bean
   public DefaultWebSecurityManager defaultWebSecurityManager() {
       // 1.创建安全管理器 defaultWebSecurityManager
       DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
       // 2.创建加密对象,其中设置加密算法，以及加密次数，注意盐信息在自定义realm中已经设置
       HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
       matcher.setHashAlgorithmName("MD5");
       matcher.setHashIterations(3);
       // 3.将加密对象添加到realm中
       customRealm.setCredentialsMatcher(matcher);
       // 4.将realm添加到安全管理器中
       defaultWebSecurityManager.setRealm(customRealm);
       /**
        * 注意此处可以添加多个realm，并且配置认证策略,策略有AllSuccessfulStrategy,AnySuccessfulStrategy,AtLeastOneSuccessfulStrategy
        * ModularRealmAuthenticator modularRealmAuthenticator = new ModularRealmAuthenticator();
        * modularRealmAuthenticator.setAuthenticationStrategy(new AllSuccessfulStrategy());
        * List<Realm> realms = new ArrayList<>();
        * realms.add(customRealm);
        * modularRealmAuthenticator.setRealms(realms);
        */
       // 设置rememberMe
       defaultWebSecurityManager.setRememberMeManager(rememberMeManager());

       // 设置缓存管理器
       defaultWebSecurityManager.setCacheManager(getEhCacheManager());

       // 5.返回安全管理器
       return defaultWebSecurityManager;
   }

   /**
    * 创建缓存管理器
    * @return
    */
    private EhCacheManager getEhCacheManager() {
        // 获取缓存管理器
        EhCacheManager ehCacheManager = new EhCacheManager();
        InputStream inputStream = null;
        try {
            inputStream = ResourceUtils.getInputStreamForPath("classpath:ehcache/ehcache-shiro.xml");
        } catch (IOException e) {
            e.printStackTrace();
        }
        CacheManager cacheManager = new CacheManager(inputStream);
        ehCacheManager.setCacheManager(cacheManager);
        return ehCacheManager;
    }

    /**
    * 创建cookie对象
    * @return
    */
   public SimpleCookie rememberMeCookie() {
       // 设置cookie名称，对应login.html页面的<input type="checkbox" name="rememberMe"/>
       SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
       // 设置cookie跨域
       simpleCookie.setDomain("localhost");
       // 设置path属性
       simpleCookie.setPath("/");
       // 设置cookie的HttpOnly属性
       simpleCookie.setHttpOnly(true);
       // 设置cookie的过期时间，单位为秒，这里为一天
       simpleCookie.setMaxAge(86400);
       return simpleCookie;
   }

   /**
    * 创建rememberMe管理器
    * @return
    */
   public CookieRememberMeManager rememberMeManager() {
       CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
       cookieRememberMeManager.setCookie(rememberMeCookie());
       // cipherKey是rememberMe cookie加密的密钥，长度必须为16位
       cookieRememberMeManager.setCipherKey("1234567890987654".getBytes(StandardCharsets.UTF_8));
       return cookieRememberMeManager;
   }

   /**
    * 创建过滤器链
    * @return
    */
   @Bean
   public DefaultShiroFilterChainDefinition shiroFilterChainDefinition() {
       DefaultShiroFilterChainDefinition filterChainDefinition = new DefaultShiroFilterChainDefinition();
       // 设置不认证可以访问资源
       filterChainDefinition.addPathDefinition("/shiro/login", "anon");
       filterChainDefinition.addPathDefinition("/login", "anon");
       // 添加登出拦截器
       filterChainDefinition.addPathDefinition("/shiro/logout", "logout");
       // 设置需要认证的拦截范围
       filterChainDefinition.addPathDefinition("/**", "authc");
       // 添加存在用户过滤器(rememberMe)
       filterChainDefinition.addPathDefinition("/**", "user");
       return filterChainDefinition;
   }

}
